package com.atwisdom.star.exception.handler;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.exception.pojo.BusinessException;
import com.atwisdom.star.exception.pojo.ErrorEnum;
import com.atwisdom.star.exception.pojo.ResultEx;
import com.atwisdom.star.exception.util.ErrorUtil;
import com.atwisdom.star.log.mapper.SysLogMapper;
import com.atwisdom.star.log.pojo.SysLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;


/**
 * 统一异常处理
 */
@Slf4j
@RestControllerAdvice("com.atwisdom.star")
public class StarExceptionHandler {

    private final SysLogMapper sysLogMapper;

    public StarExceptionHandler(SysLogMapper sysLogMapper) {
        this.sysLogMapper = sysLogMapper;
    }

    /**
     * 业务异常 统一处理
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public Object businessExceptionHandler(BusinessException e, HttpServletRequest request){
        StringBuilder requestBody = new StringBuilder();
        String line;
        BufferedReader reader = null;
        try {
            reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                requestBody.append(line);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        log.error("environment:"+request.getHeader("debug"));
        log.error("request:"+request.getRequestURI());
        log.error("params:"+ requestBody);
        log.error("business error info: {}", e.getMessage());
        log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        return doBusinessException(e, request);
    }

    /**
     * 空指针异常 统一处理
     */
    @ExceptionHandler(value =NullPointerException.class)
    @ResponseBody
    public Object nullPointerExceptionHandler(NullPointerException e){
        return doException(e,ErrorEnum.INTERNAL_SERVER_ERROR);
    }

    /**
     * 未知异常 统一处理
     */
    @ExceptionHandler(value =Exception.class)
    @ResponseBody
    public Object exceptionHandler(Exception e){
        log.error("error info: {}", e.getMessage());
        BusinessException be = new BusinessException(e);
        return doException(be,ErrorEnum.INTERNAL_SERVER_ERROR);
    }

    /**
     * 异常处理
     * @param e
     * @param errorEnum
     * @return
     */
    private Object doException(Exception e,ErrorEnum errorEnum){
        //把错误信息输入到日志中
        String errorInfo = ErrorUtil.errorInfoToString(e);
        String msg = errorEnum==null?e.getMessage():errorEnum.getMsg();
        String code = errorEnum==null?"500":errorEnum.getCode();
        SysLog log=new SysLog(errorInfo,msg);
        this.sysLogMapper.insert(log);
        return ResultEx.ex(code,msg);
    }

    /**
     * 处理自定义业务异常
     * @param e
     * @return
     */
    private Object doBusinessException(BusinessException e, HttpServletRequest request){
        String errorInfo = ErrorUtil.errorInfoToString(e);
        // log.error(errorInfo);
        String msg = e.getErrorMsg();
        String code =e.getCode();
        String requestIp = getIP(request);
        log.info("requestIP = {}", requestIp);
        SysLog sysLog =new SysLog(errorInfo,msg, requestIp);
        this.sysLogMapper.insert(sysLog);
        return ResultEx.ex(code,msg);

    }

    public static String getIP(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        ip = checkIp(ip) ? ip : (
                checkIp(ip = request.getHeader("Proxy-Client-IP")) ? ip : (
                        checkIp(ip = request.getHeader("WL-Proxy-Client-IP")) ? ip :
                                request.getRemoteAddr()));
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

    private static boolean checkIp(String ip) {
        return !StrUtil.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip);
    }
}
